import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:mongo_dart/mongo_dart.dart';
import 'package:backend.user_profile/domain/entities/password_reset_token.dart';
import 'package:backend.user_profile/domain/repositories/password_reset_token_repository/repository.dart';

part 'dtos/password_reset_token_dto.dart';

part 'dtos/time_dto.dart';

const _kPasswordResetTokenCollectionKey = 'password_reset_tokens';

class PasswordResetTokenRepositoryImpl implements PasswordResetTokenRepository {
  const PasswordResetTokenRepositoryImpl({
    required Db db,
  }) : _db = db;

  final Db _db;

  @override
  Future<PasswordResetToken?> findPasswordResetTokenByValue({
    required String value,
  }) async {
    final collection = _db.collection(_kPasswordResetTokenCollectionKey);

    final data = await collection.findOne(
      where.eq(_kPasswordResetTokenValueKey, value),
    );

    if (data == null) {
      return null;
    }

    final passwordResetTokenDto = _PasswordResetTokenDto.fromJson(data);
    final passwordResetToken = passwordResetTokenDto.toEntity();

    return passwordResetToken;
  }

  @override
  Future<BuiltList<PasswordResetToken>> findPasswordResetTokens() async {
    final collection = _db.collection(_kPasswordResetTokenCollectionKey);

    final passwordResetTokenJsonStream = collection.find();

    final passwordResetTokenJsons = await passwordResetTokenJsonStream.toList();

    final passwordResetTokens = passwordResetTokenJsons.map((passwordResetTokenJson) {
      final passwordResetTokenDto = _PasswordResetTokenDto.fromJson(passwordResetTokenJson);
      return passwordResetTokenDto.toEntity();
    }).toBuiltList();

    return passwordResetTokens;
  }

  @override
  Future<void> upsertPasswordResetToken({
    required PasswordResetToken passwordResetToken,
  }) async {
    final collection = _db.collection(_kPasswordResetTokenCollectionKey);

    final passwordResetTokenDto = _PasswordResetTokenDto.fromEntity(passwordResetToken);
    final passwordResetTokenJson = passwordResetTokenDto.toJson();

    await collection.replaceOne(
      where.eq(_kPasswordResetTokenUserIdKey, passwordResetToken.userId),
      passwordResetTokenJson,
      upsert: true,
    );
  }

  @override
  Future<void> deletePasswordResetTokenByValue({
    required String value,
  }) async {
    final collection = _db.collection(_kPasswordResetTokenCollectionKey);

    await collection.deleteOne(
      where.eq(_kPasswordResetTokenValueKey, value),
    );
  }

  @override
  Future<void> deletePasswordResetTokensByValues({
    required BuiltList<String> values,
  }) async {
    final collection = _db.collection(_kPasswordResetTokenCollectionKey);

    await collection.deleteMany(
      where.oneFrom(_kPasswordResetTokenValueKey, values.toList()),
    );
  }
}
